package com.lz.ub.hm.impl

import com.lz.ub.*
import com.lz.ub.hm.*

/**
 * @author you
 * HM厂家的解析
 */
class HMUBReader(override val handler: UBHandler) : UBReader {

    companion object {
        //发送响应头, +开关
        const val SEND_HEAD_R: Byte = 0x2B
        //收到响应头 [
        const val RCV_HEAD_R: Byte = 0x5B
        //指令开头分割符  :
        const val COMMAND_SPLIT: Byte = 0x3A
        //指令分割 ,
        const val COMMAND_SPLIT2: Byte = 0x2C
        //连接响应
        const val SEND_CONN = "CONN"
        //断开连接响应
        const val SEND_DISCONN = "DISCON"
        //连接err
        const val SEND_ERR = "ERR"
        //连接handle属性
        const val SEND_PORT = "TXPORT"
        //发送的响应
        const val SEND_SEND = "SEND"
        //ok响应
        const val OK = "OK"

        //连接时对方BLE的响应
        const val BLE = "[BLE]"
        //查找BLE后面指令的开始处, 包含:
        const val BLE_START = BLE.length + 1
        //连接时对方RCV的响应
        const val RCV = "[RCV]"
        //接收数据时的link索引
        const val RCV_LINK_INDEX = 6
        //BLE连接成功
        const val CONNECTED = "Connected"
        //BLE连接断开
        const val DISCONNECTED = "Disconnect"
        //收到的扫描结果
        const val SCAN = "[SCAN]"
        //收到的扫描结果
        const val SCAN_SPLIT = "[SCAN]:"
        //扫描结果分割
        const val SCAN_RESULT_SPLIT = ','

        //最小响应长度
        const val MIN_LEN = 2

        const val TAG = "HMUBReader"

        /**
         * 找出split分割的开头
         * @param split 分割字符
         * @param start 去除的字符开始
         */
        fun findSplitStart(bytes: ByteArray, split: Byte = COMMAND_SPLIT, start: Int = 0): String {
            val index = splitIndex(bytes, split, start)
            return if (index == -1) "" else String(bytes, start, index - start)
        }

        /**
         * 找出split分割两边的字符串
         * @param split 分割字符
         * @param start 去除的字符开始
         */
        fun findSplits(bytes: ByteArray, split: Byte = COMMAND_SPLIT, start: Int = 0): Array<String> {
            val result = arrayOf("", "")
            val index = splitIndex(bytes, split, start)
            if (index != -1) {
                result[0] = String(bytes, start, index - start)
                result[1] = String(bytes, index + 1, bytes.size - index - 1)
            }
            return result
        }

        //分割符的索引
        private fun splitIndex(bytes: ByteArray, split: Byte, start: Int): Int {
            for (i in start until bytes.size) {
                if (bytes[i] == split) return i
            }
            return -1
        }

        fun str2int(str: String): Int = str.toIntOrNull() ?: INVALID
    }

    override fun onReceivedData(bytes: ByteArray?) {
        if (bytes == null || bytes.size <= MIN_LEN) {
            Logger.d(TAG, "received data len < $MIN_LEN")
            return
        }
        Logger.d(TAG, "received = ${bytes.size},  ${String(bytes)}<====----")
        when (val first = bytes[0]) {
            SEND_HEAD_R -> sendCommandResponse(bytes)
            RCV_HEAD_R -> bleRcvCommandResponse(bytes)
            else -> { Logger.i(TAG, "unknown commands $first") } //主板出现问题时的响应
        }
    }

    //主板发送的指令响应, 如CONN:OK, ERR:6, SEND:OK, TXPORT:OK等
    private fun sendCommandResponse(bytes: ByteArray) {
        val commands = findSplits(bytes, start = 1) //1去除+号
        //注意线上打包去掉此注释
//        Logger.i(TAG, "board command ${commands[0]}-${commands[1]}<====----")
        when (commands[0]) {
            //连接状态响应, OK只能代表请求发送成功, 一般都是响应OK,否则就响应+ERR
            SEND_CONN -> handler.sendConnectedStateChanged(SUCCESS, if (commands[1].trim() == OK) SUCCESS else FAILED)
            SEND_DISCONN -> {
                //+DISCON:OK \n\t [BLE]:Disconnect,1 处理指令并行的情况
                val index = commands[1].indexOf(BLE)
                if (index < 0) {
                    handler.sendConnectedStateChanged(FAILED, if (commands[1].trim() == OK) SUCCESS else FAILED)
                } else {
                    val disArr = commands[1].substring(index + BLE.length + 1, commands[1].length).split(',')
                    val link = disArr.getOrNull(1)?.trim()?.toIntOrNull()
                    if (disArr.getOrNull(0) == DISCONNECTED && link != null) {
                        handler.sendServiceStateChanged(FAILED, link)
                    } else {
                        val result = commands[1].substring(0, index).trim()
                        Logger.i(TAG, "disconnect ok and data is Null ==>$result")
                        handler.sendConnectedStateChanged(FAILED, if (result == OK) SUCCESS else FAILED)
                    }
                }
            }
            //属性handler设置响应
            SEND_PORT -> handler.sendPropertyStateChanged(if (commands[1].trim() == OK) SUCCESS else FAILED)
            SEND_SEND -> handler.sendWrite(if (commands[1].trim() == OK) SUCCESS else FAILED)
            //错误指令
            SEND_ERR -> handler.sendError(commands[1].trim())
        }
    }



    //Ble 响应后主板收到的指令
    private fun bleRcvCommandResponse(bytes: ByteArray) {
        val bleRcvCommand = findSplitStart(bytes)
        Logger.i(TAG, "bleRcvCommandResponse = $bleRcvCommand")
        when (bleRcvCommand) {
            BLE -> {
                val resp = findSplits(bytes, COMMAND_SPLIT2, BLE_START)
                Logger.i(TAG, "Ble resp =${resp[0]},  ${resp[1]}<====----")
                when (resp[0]) {
                    CONNECTED -> handler.sendServiceStateChanged(SUCCESS, str2int(resp[1].trim()))
                    DISCONNECTED -> handler.sendServiceStateChanged(FAILED, str2int(resp[1].trim()))
                }
            }
            RCV -> {
                val linkStr = findSplitStart(bytes, COMMAND_SPLIT2, RCV_LINK_INDEX)
                val sizeStr = findSplitStart(bytes, COMMAND_SPLIT2, RCV_LINK_INDEX + linkStr.length + 1)
                val start = RCV_LINK_INDEX + linkStr.length + sizeStr.length + 2
                handler.sendRead(linkStr.toInt(), bytes, start.shl(8) + sizeStr.toInt())
            }
            SCAN -> {
                var list: ArrayList<UBScanResult>? = null
                String(bytes, SCAN_SPLIT.length, bytes.size - SCAN_SPLIT.length).split(SCAN_SPLIT).forEach {
                    val res = it.trimEnd().split(SCAN_RESULT_SPLIT)
                    if (res.size in 5..6 && res[1] == "0" && (res[2] == "0" || res[2] == "1")) {
                        if (list == null) list = ArrayList()
                        list!!.add(UBScanResult(res[3], res[2].toInt(), res[4], res.getOrNull(5) ?: "N/A"))
                    }
                }
                if (list != null) {
                    handler.sendScanResult(list!!)
                }
            }
        }
    }

    override fun onCTSChanged(state: Boolean) = Unit

    override fun onDSRChanged(state: Boolean) = Unit
}